<template>
<div class="proxy-container">
  <div class="proxy-content">
    <div class="control-panel">
      <div class="status-info">
        <div class="status-card">
          <div class="status-icon">
            <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
              <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
            </svg>
          </div>
          <div class="status-details">
            <span class="status-label">代理状态</span>
            <span class="status-value" :class="{'status-running': proxyStatus === 'Running', 'status-stopped': proxyStatus === 'Stopped'}">
              {{ proxyStatus }}
            </span>
          </div>
        </div>
        <div class="status-card">
          <div class="status-icon">
            <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
              <rect x="2" y="2" width="20" height="8" rx="2" ry="2"/>
              <rect x="2" y="14" width="20" height="8" rx="2" ry="2"/>
              <line x1="6" y1="6" x2="6.01" y2="6"/>
              <line x1="6" y1="18" x2="6.01" y2="18"/>
            </svg>
          </div>
          <div class="status-details">
            <span class="status-label">端口</span>
            <span class="status-value">{{ proxyPort }}</span>
          </div>
        </div>
      </div>
      <div 
        @click="toggleProxy" 
        class="toggle-proxy-icon"
        :title="isProxyRunning ? '停止代理' : '启动代理'"
      >
        <svg v-if="!isProxyRunning" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
          <polygon points="5 3 19 12 5 21 5 3"></polygon>
        </svg>
        <svg v-else xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
          <rect x="6" y="4" width="4" height="16"></rect>
          <rect x="14" y="4" width="4" height="16"></rect>
        </svg>
      </div>
      <div 
        @click="handleInstallCert" 
        class="install-icon-wrapper"
        title="安装证书"
      >
        <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
          <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/>
          <path d="M3 21l7-7"/>
          <path d="M12.5 5.5L18 11"/>
        </svg>
      </div>
      <div 
        @click="clearRequests" 
        class="clear-icon-wrapper"
        title="清除所有请求"
      >
        <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <path d="M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
        </svg>
      </div>
      <div 
        @click="toggleSettings" 
        class="settings-icon-wrapper"
        :class="{ 'active': showSettings }"
        title="设置"
      >
        <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
          <circle cx="12" cy="12" r="3"></circle>
          <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
        </svg>
      </div>
      
    </div>
    
    <div class="request-list">
      <div class="search-box" v-if="filteredRequests && filteredRequests.length > 0">
        <input 
          type="text" 
          v-model="searchQuery" 
          placeholder="搜索 URL..."
          class="search-input"
        />
        <svg class="search-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <circle cx="11" cy="11" r="8"></circle>
          <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
        </svg>

        <button 
          v-show="searchQuery"
          @click="searchQuery = ''" 
          class="search-clear-btn"
          title="Clear search"
        >
          <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <line x1="18" y1="6" x2="6" y2="18"></line>
            <line x1="6" y1="6" x2="18" y2="18"></line>
          </svg>
        </button>
      </div>
      <div class="request-items-container">
        <div v-for="(req, index) in filteredRequests" :key="index" 
            class="request-item" 
            :class="{ selected: selectedRequest?.id === req.id }"
            @click="selectRequest(req)">
          <div class="request-basic-info">
            <span class="method" :class="req.method.toLowerCase()">{{ req.method }}</span>
            <span class="url" :title="req.url">{{ req.url }}</span>
            <span class="status" :class="getStatusClass(req.response?.statusCode)">
              {{ req.response?.statusCode || 'Pending' }}
            </span>
          </div>
        </div>
      </div>
      <div class="pagination" v-if="filteredRequests && filteredRequests.length > 0">
        <button 
          @click="currentPage = 1"
          :disabled="currentPage === 1"
          class="pagination-btn"
        >≪</button>
        <button 
          @click="currentPage--"
          :disabled="currentPage === 1"
          class="pagination-btn"
        >‹</button>
        
        <div class="page-numbers">
          <button 
            v-for="page in totalPages"
            :key="page"
            @click="currentPage = page"
            :class="['page-number', { active: currentPage === page }]"
            v-show="shouldShowPage(page)"
          >{{ page }}</button>
        </div>

        <button 
          @click="currentPage++"
          :disabled="currentPage === totalPages"
          class="pagination-btn"
        >›</button>
        <button 
          @click="currentPage = totalPages"
          :disabled="currentPage === totalPages"
          class="pagination-btn"
        >≫</button>
      </div>

    </div>

    <div class="request-detail" v-if="selectedRequest">
      <div class="detail-tabs">
        <button 
          v-for="tab in tabs" 
          :key="tab"
          :class="{ active: currentTab === tab }"
          @click="currentTab = tab">
          {{ tab }}
        </button>
      </div>

      <div class="detail-content">
        <div v-if="currentTab === 'Headers'" class="headers-panel">
          <div class="request-headers">
            <h4>Request Headers</h4>
            <div class="header-url"><strong>URL:</strong> {{ selectedRequest.url }}</div>
            <div v-for="(value, key) in selectedRequest.headers" :key="key">
              <strong>{{ key }}:</strong> {{ value }}
            </div>
          </div>
          <div class="response-headers" v-if="selectedRequest.response">
            <h4>Response Headers</h4>
            <div v-for="(value, key) in selectedRequest.response.headers" :key="key">
              <strong>{{ key }}:</strong> {{ value }}
            </div>
          </div>
        </div>

        <div v-else-if="currentTab === 'Body'" class="body-panel">
          <div class="request-body">
            <h4>Request Body</h4>
            <pre>{{ formatBody(selectedRequest.body) }}</pre>
          </div>
          <div class="response-body" v-if="selectedRequest.response">
            <h4>Response Body</h4>
            <virtual-text-viewer 
              :text="formatBody(selectedRequest.response.body)"
              :max-height="250"
            />
          </div>
        </div>
      </div>
    </div>

    <div 
      v-if="showSettings"
      class="settings-overlay"
      @click="toggleSettings"
    ></div>

    <div 
      class="settings-drawer"
      :class="{ 'settings-drawer-open': showSettings }"
    >
      <div class="settings-drawer-content">
        <div class="settings-header">
          <h3>设置</h3>
          <button @click="toggleSettings" class="close-settings-btn">
            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <line x1="18" y1="6" x2="6" y2="18"></line>
              <line x1="6" y1="6" x2="18" y2="18"></line>
            </svg>
          </button>
        </div>
        
        <div class="settings-body">
          <div class="settings-item">
            <label for="proxyPort">代理端口</label>
            <div class="port-input-group">
              <input 
                type="number" 
                id="proxyPort"
                v-model="tempProxyPort"
                :disabled="isProxyRunning"
                min="1"
                max="65535"
              />
              <button 
                @click="savePort" 
                :disabled="isProxyRunning || !isPortChanged"
                class="save-port-btn"
              >
                保存
              </button>
            </div>
            <p class="port-hint" v-if="isProxyRunning">
              请先停止代理服务后再修改端口
            </p>
          </div>

          <div class="settings-item">
            <label>证书</label>
            <div class="cert-location-group">
              <div class="cert-path" :title="certPath">{{ certPath || '未找到证书' }}</div>
              <button 
                @click="openCertLocation" 
                :disabled="!certPath"
                class="open-location-btn"
              >
                打开
              </button>
            </div>
          </div>

          <div class="settings-item">
            <label for="proxyPort">测试证书</label>
            <div class="port-input-group">
              <input 
                v-model="domainUrl"
                placeholder="输入测试网页地址"
              />
              <button 
                @click="testCert" 
                class="save-port-btn"
              >
                测试
              </button>
            </div>
          </div>

        </div>

        <div class="app-info">
          <div class="app-info-content" @click="openGitRepo">
            <img src="@/assets/logo.png" alt="App Logo" class="app-logo" />
            <div class="app-details">
              <div class="app-name">嘉仪 HTTP Proxy Tool</div>
              <div class="app-version">Version 0.0.1</div>
            </div>
            <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="arrow-icon">
              <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
              <polyline points="15 3 21 3 21 9"></polyline>
              <line x1="10" y1="14" x2="21" y2="3"></line>
            </svg>
          </div>
        </div>

      </div>
    </div>
    
  </div>
</div>
</template>

<script>
import { ipcRenderer, shell } from 'electron'
import VirtualTextViewer from './VirtualTextViewer.vue'
import { ElMessage } from 'element-plus'

export default {
  name: 'ProxyView',
  components: {
    VirtualTextViewer
  },
  data() {
    return {
      proxyStatus: 'Stopped',
      proxyPort: 33120,
      isProxyRunning: false,
      isLoading: false,
      requests: [],
      selectedRequest: null,
      currentTab: 'Headers',
      tabs: ['Headers', 'Body'],
      certPath: null,
      searchQuery: '',
      currentPage: 1,
      itemsPerPage: 10,
      showSettings: false,
      tempProxyPort: 33120,
      domainUrl: 'www.baidu.com',
      gitUrl: 'https://gitee.com/auhgnep'
    }
  },

  computed: {
    filteredRequests() {
      const query = this.searchQuery.toLowerCase().trim()
      const filtered = query 
        ? this.requests.filter(req => req.url.toLowerCase().includes(query))
        : this.requests
      
      const start = (this.currentPage - 1) * this.itemsPerPage
      const end = start + this.itemsPerPage
      return filtered.slice(start, end)
    },
  
    totalPages() {
      const filtered = this.searchQuery.toLowerCase().trim()
        ? this.requests.filter(req => req.url.toLowerCase().includes(this.searchQuery.toLowerCase().trim()))
        : this.requests
      return Math.ceil(filtered.length / this.itemsPerPage)
    },

    isPortChanged() {
      return this.tempProxyPort !== this.proxyPort
    }
  },

  async mounted() {
    this.setupListeners()
    this.certPath = await ipcRenderer.invoke('proxy:getCertPath')
  },

  methods: {
    toggleSettings() {
      this.showSettings = !this.showSettings
      if (this.showSettings) {
        this.tempProxyPort = this.proxyPort
      }
    },

    async savePort() {
      if (this.tempProxyPort < 1 || this.tempProxyPort > 65535) {
        ElMessage.error('端口号必须在 1-65535 之间')
        return
      }
      
      this.proxyPort = this.tempProxyPort
      ElMessage.success('端口设置已保存')
    },
    clearRequests() {
      this.requests = []
      this.selectedRequest = null
      this.currentPage = 1
      this.searchQuery = ''
    },
    shouldShowPage(page) {
      if (this.totalPages <= 7) return true
      if (page === 1 || page === this.totalPages) return true
      if (page >= this.currentPage - 1 && page <= this.currentPage + 1) return true
      return false
    },
    setupListeners() {
      ipcRenderer.on('proxy:status', (event, data) => {
        this.proxyStatus = data.status
        this.proxyPort = data.port
        this.isProxyRunning = true
        this.isLoading = false
      })

      ipcRenderer.on('proxy:error', (event, data) => {
        this.proxyStatus = 'Error'
        this.isLoading = false
        console.error(data.error)
      })

      ipcRenderer.on('proxy:request', (event, data) => {
        this.requests.unshift({
          ...data,
          timestamp: Date.now()
        })
      })

      ipcRenderer.on('proxy:response', (event, data) => {
        const request = this.requests.find(req => req.id === data.id)
        if (request) {
          request.response = data
        }
      })
    },

    async toggleProxy() {
      this.isLoading = true
      if (this.isProxyRunning) {
        const result = await ipcRenderer.invoke('proxy:stop')
        if (result.success) {
          this.isProxyRunning = false
          this.proxyStatus = 'Stopped'
        }
      } else {
        await ipcRenderer.invoke('proxy:start', this.proxyPort)
      }
      this.isLoading = false
    },

    selectRequest(request) {
      this.selectedRequest = request
      this.currentTab = 'Headers'
    },

    getStatusClass(status) {
      if (!status) return 'pending'
      if (status < 300) return 'success'
      if (status < 400) return 'redirect'
      if (status < 500) return 'client-error'
      return 'server-error'
    },

    formatBody(body) {
      if (!body) return ''
      try {
        return JSON.stringify(JSON.parse(body), null, 2)
      } catch {
        return body
      }
    },

    async openCertLocation() {
      if (this.certPath) {
        await shell.showItemInFolder(this.certPath)
        ElMessage({
          message: '打开成功，已打开文件窗口',
          type: 'success',
        })
      }
    },

    async handleInstallCert() {
      try {
        const result = await ipcRenderer.invoke('proxy:installCert')
        if (result.success) {
          // 显示成功消息
          console.log('安装成功')
          ElMessage({
            message: '安装成功',
            type: 'success',
          })
        } else {
          // 显示错误消息
          ElMessage.error('安装失败：' + result.message)
          console.log('安装失败', result)
        }
      } catch (error) {
        console.error('安装证书失败:', error)
      }
    },

    async testCert() {
      const result = await ipcRenderer.invoke('proxy:testCert', this.domainUrl)
      if (result.success) {
        ElMessage({
          message: '测试成功，证书正常',
          type: 'success',
        })
      } else {
        ElMessage.error('测试证书失败：' + result.message)
      }
    },

    async openGitRepo() {
      await shell.openExternal(this.gitUrl)
    },
  }
}
</script>

<style scoped>
.proxy-container {
  height: 100%;
  overflow-x: auto;
  background: #f8f9fa;
}

.proxy-content {
  display: grid;
  grid-template-rows: auto 1fr;
  grid-template-columns: 350px 1fr;
  gap: 1.5rem;
  padding: 1.5rem;
  min-width: 700px;  /* 设置最小宽度 */
  width: 100%;      /* 确保容器填充可用空间 */
  min-height: 500px;
  height: 100%;
}

.control-panel {
  grid-column: 1 / -1;
  display: flex;
  gap: 1rem;
  padding: 1.25rem;
  background: white;
  border-radius: 10px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.08);
}

.status-info {
  display: flex;
  gap: 1.5rem;
  align-items: center;
  margin-right: auto;
}

.status-card {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 1rem;
  background: #f8fafc;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  transition: all 0.2s ease;
  cursor: pointer;
  min-width: 160px; /* 添加最小宽度 */
  width: 160px;    /* 固定宽度 */
}

.status-details {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  flex: 1;         /* 让详情区域填充剩余空间 */
  min-width: 0;    /* 防止子元素溢出 */
}

.status-value {
  font-size: 0.875rem;
  font-weight: 600;
  color: #2c3e50;
  white-space: nowrap;  /* 防止文字换行 */
  overflow: hidden;     /* 超出部分隐藏 */
  text-overflow: ellipsis; /* 超出显示省略号 */
}

.status-running {
  color: #27ae60;
}

.status-stopped {
  color: #e74c3c;
}

.status-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #3498db;
  flex-shrink: 0;  /* 防止图标缩小 */
  width: 24px;     /* 固定图标容器宽度 */
}

.control-panel button {
  padding: 0.5rem 1.25rem;
  border: none;
  border-radius: 6px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s ease;
  background: #3498db;
  color: white;
  display: flex;
  align-items: center;
  gap: 0.1rem;
}

.control-panel button:hover {
  background: #2980b9;
  transform: translateY(-1px);
}

.control-panel button:disabled {
  background: #95a5a6;
  cursor: not-allowed;
  transform: none;
}

.request-list {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.request-item {
  padding: 0.75rem;
  cursor: pointer;
  border-radius: 6px;
  margin-bottom: 0.5rem;
  transition: all 0.2s ease;
  border: 1px solid #edf2f7;
}

.request-basic-info {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.request-item:hover {
  background: #f8fafc;
  transform: translateX(2px);
}

.request-item.selected {
  background: #e3f2fd;
  border-color: #3498db;
}

.search-box {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 1rem;
}

.request-items-container {
  min-height: 200px;
  max-height: 50vh;
  overflow-y: auto;
  scroll-behavior: smooth;
  overflow-x: hidden;
}

.search-input {
  width: 100%;
  padding: 0.75rem 1rem 0.75rem 2.5rem;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  background-color: #ffffff;
  font-size: 0.875rem;
  color: #1a202c;
  transition: all 0.2s ease;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}

.search-input:focus {
  outline: none;
  border-color: #3498db;
  box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);
}

.search-input::placeholder {
  color: #a0aec0;
}

.search-icon {
  position: absolute;
  left: 2rem;
  top: 50%;
  transform: translateY(-50%);
  color: #718096;
  pointer-events: none;
  transition: color 0.2s ease;
}

.search-input:focus + .search-icon {
  color: #3498db;
}

.method {
  padding: 4px 8px;
  border-radius: 4px;
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.5px;
}

.method.get { 
  background: rgba(52, 152, 219, 0.1); 
  color: #3498db; 
}

.method.post { 
  background: rgba(46, 204, 113, 0.1); 
  color: #27ae60; 
}

.method.put { 
  background: rgba(243, 156, 18, 0.1); 
  color: #f39c12; 
}

.method.delete { 
  background: rgba(231, 76, 60, 0.1); 
  color: #c0392b; 
}

.url {
  flex: 1;
  max-width: 500px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: #2c3e50;
  cursor: help;
  position: relative;
}

.url:hover::after {
  content: attr(title);
  position: absolute;
  left: 0;
  top: 100%;
  z-index: 1;
  background: #2c3e50;
  color: white;
  padding: 0.5rem;
  border-radius: 4px;
  font-size: 0.875rem;
  white-space: normal;
  max-width: 400px;
  word-break: break-all;
  box-shadow: 0 2px 12px rgba(0,0,0,0.15);
}

.status {
  font-weight: 600;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 0.85rem;
}

.status.success { 
  background: rgba(46, 204, 113, 0.1);
  color: #27ae60; 
}

.status.redirect { 
  background: rgba(243, 156, 18, 0.1);
  color: #f39c12; 
}

.status.client-error { 
  background: rgba(231, 76, 60, 0.1);
  color: #c0392b; 
}

.status.server-error { 
  background: rgba(155, 89, 182, 0.1);
  color: #8e44ad; 
}

.request-detail {
  background: white;
  border-radius: 10px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.08);
  overflow: hidden;
}

.detail-tabs {
  display: flex;
  gap: 1rem;
  padding: 1rem 1.5rem;
  background: #f8fafc;
  border-bottom: 1px solid #edf2f7;
}

.detail-tabs button {
  padding: 0.5rem 1rem;
  border: none;
  background: none;
  color: #64748b;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s ease;
  position: relative;
}

.detail-tabs button.active {
  color: #3498db;
}

.detail-tabs button.active::after {
  content: '';
  position: absolute;
  bottom: -1rem;
  left: 0;
  width: 100%;
  height: 2px;
  background: #3498db;
}

.detail-content {
  padding: 1.5rem;
  height: calc(100vh - 250px); /* Adjust based on your header heights */
  overflow-y: auto;
}

.body-panel {
  display: flex;
  flex-direction: column;
  height: 100%;
  gap: 1.5rem;
}

.response-body {
  flex: 1;
}

pre {
  white-space: pre-wrap;
  word-wrap: break-word;
  background: #f8fafc;
  padding: 1.25rem;
  border-radius: 8px;
  border: 1px solid #edf2f7;
  font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
  font-size: 0.9rem;
  line-height: 1.5;
  color: #2c3e50;
}

.headers-panel div {
  padding: 0.5rem;
  border-radius: 4px;
  background: #f8fafc;
  word-break: break-all;
  overflow-wrap: break-word;
  max-width: 100%;
}

.response-headers {
  margin-top: 1.5rem;
}

/* 增加动画效果 */
.request-headers, .response-headers,
.request-body, .response-body {
  opacity: 0;
  animation: fadeIn 0.3s ease forwards;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.header-url {
  word-wrap: break-word;
  word-break: break-all;
  overflow-wrap: break-word;
  max-width: 100%;
}

.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.5rem;
  padding: 1rem;
  margin-top: auto;
  border-top: 1px solid #edf2f7;
  width: 350px; 
}

.pagination-btn {
  padding: 0.5rem 0.75rem;
  border: 1px solid #e2e8f0;
  background: white;
  color: #2d3748;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.pagination-btn:hover:not(:disabled) {
  background: #f7fafc;
  border-color: #cbd5e0;
}

.pagination-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.page-numbers {
  display: flex;
  gap: 0.25rem;
}

.page-number {
  padding: 0.5rem 0.75rem;
  border: 1px solid #e2e8f0;
  background: white;
  color: #2d3748;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
  min-width: 2.5rem;
}

.page-number:hover:not(.active) {
  background: #f7fafc;
  border-color: #cbd5e0;
}

.page-number.active {
  background: #3498db;
  color: white;
  border-color: #3498db;
}

.search-input {
  padding-right: 3.5rem;
}

.search-clear-btn {
  position: absolute;
  right: 2rem;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  padding: 0.5rem;
  color: #718096;
  cursor: pointer;
  border-radius: 6px;
  transition: all 0.2s ease;
  display: flex;
  align-items: center;
}

.search-clear-btn:hover {
  background: #f7fafc;
  color: #4a5568;
}

.settings-icon-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem;
  cursor: pointer;
  color: #64748b;
  border-radius: 6px;
  transition: all 0.2s ease;
  margin-left: 0.5rem;
}

.settings-icon-wrapper:hover {
  color: #3498db;
  animation: spin 2s linear infinite;
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.settings-drawer {
  position: fixed;
  top: 0;
  right: -400px;
  width: 400px;
  height: 100vh;
  background: white;
  box-shadow: -2px 0 12px rgba(0,0,0,0.1);
  transition: right 0.3s ease;
  z-index: 1000;
}

.settings-drawer-open {
  right: 0;
}

.settings-drawer-content {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.settings-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1.5rem;
  border-bottom: 1px solid #edf2f7;
}

.settings-header h3 {
  margin: 0;
  font-size: 1.25rem;
  color: #2d3748;
}

.close-settings-btn {
  background: none;
  border: none;
  padding: 0.5rem;
  cursor: pointer;
  color: #718096;
  border-radius: 6px;
  transition: all 0.2s ease;
}

.close-settings-btn:hover {
  background: #f7fafc;
  color: #4a5568;
}

.settings-body {
  padding: 1.5rem;
  flex: 1;
  overflow-y: auto;
}

.settings-item {
  margin-bottom: 1.5rem;
}

.settings-item label {
  display: block;
  margin-bottom: 0.5rem;
  color: #4a5568;
  font-weight: 500;
}

.port-input-group {
  display: flex;
  gap: 0.5rem;
}

.port-input-group input {
  flex: 1;
  padding: 0.5rem;
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  font-size: 0.875rem;
}

.port-input-group input:disabled {
  background: #f7fafc;
  cursor: not-allowed;
}

.save-port-btn {
  padding: 0.5rem 1rem;
  background: #3498db;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.save-port-btn:hover:not(:disabled) {
  background: #2980b9;
}

.save-port-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.port-hint {
  margin-top: 0.5rem;
  font-size: 0.875rem;
  color: #e74c3c;
}

.cert-location-group {
  display: flex;
  gap: 0.5rem;
}

.cert-path {
  flex: 1;
  font-size: 0.875rem;
  color: #4a5568;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 0.5rem;
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 6px;
}

.open-location-btn {
  padding: 0.5rem 1rem;
  background: #3498db;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
  white-space: nowrap;
}

.open-location-btn:hover:not(:disabled) {
  background: #2980b9;
}

.open-location-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background: #a0aec0;
}

.settings-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.3);
  z-index: 999;
  backdrop-filter: blur(2px);
  transition: opacity 0.3s ease;
}

.clear-icon-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem;
  cursor: pointer;
  color: #64748b;
  border-radius: 6px;
  transition: all 0.2s ease;
}

.clear-icon-wrapper:hover {
  color: #e74c3c;
  animation: shake 0.5s ease-in-out infinite;
}

@keyframes shake {
  0% { transform: rotate(0deg); }
  25% { transform: rotate(-10deg); }
  75% { transform: rotate(10deg); }
  100% { transform: rotate(0deg); }
}

.install-icon-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem;
  cursor: pointer;
  color: #64748b;
  border-radius: 6px;
  transition: all 0.2s ease;
}

.install-icon-wrapper:hover {
  color: #27ae60;
  animation: bounce 0.5s ease infinite;
}

@keyframes bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-3px); }
}

.toggle-proxy-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem;
  cursor: pointer;
  color: #3498db;
  border-radius: 6px;
  transition: all 0.2s ease;
}

.toggle-proxy-icon:hover {
  /* background: rgba(52, 152, 219, 0.2); */
  transform: scale(1.25);
}

.toggle-proxy-icon:active {
  transform: scale(0.95);
}

.toggle-proxy-icon[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

.app-info {
  margin-top: auto;
  padding: 1.5rem;
  border-top: 1px solid #edf2f7;
}

.app-info-content {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem;
  border-radius: 12px;
  background: linear-gradient(145deg, #f8fafc, #ffffff);
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
  cursor: pointer;
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
}

.app-info-content:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 12px -1px rgba(0, 0, 0, 0.15), 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

.app-info-content::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.1), transparent);
  transform: translateX(-100%);
  transition: transform 0.6s ease;
}

.app-info-content:hover::before {
  transform: translateX(100%);
}

.app-logo {
  width: 48px;
  height: 48px;
  border-radius: 10px;
  object-fit: cover;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.app-details {
  flex: 1;
}

.app-name {
  font-weight: 600;
  color: #2d3748;
  font-size: 1.1rem;
  margin-bottom: 0.25rem;
}

.app-version {
  color: #718096;
  font-size: 0.875rem;
}

.arrow-icon {
  color: #3498db;
  opacity: 0;
  transform: translateX(-10px);
  transition: all 0.3s ease;
}

.app-info-content:hover .arrow-icon {
  opacity: 1;
  transform: translateX(0);
}

</style>
